#ifndef PROCESS_MONITOR_H_
#define PROCESS_MONITOR_H_

#include <time.h>
#include <sched.h>  /* For __CPU_SETSIZE */
#include <limits.h>
#include <stdlib.h>
#include <list>
#include <map>
#include <string>
#include <stdint.h>
#include <unordered_map>

#include "BasicExcel.hpp"
//#include "application/application.h"
#include "common.h"
//#include "linux/linux_util.h" 
//#include "deamon/cgroup_manager.h"
//#include "deamon/cpu_affinity.h"

namespace xag {
namespace xos {
namespace deamon {


struct SysMonitorStats {
  std::string ts;
};

struct MonitorInfo {
  bool exits;
  SysMonitorStats sys_stats[2];
  std::map<pid_t,st_pid> all_process_map;
};

struct ExcelTool {
  YExcel::BasicExcel excel;
  std::string excel_name;
};

struct SysCpuState {
  double cpu_utilization;
  double cpu_temperature;
  double user;
  double nice;
  double system;
  double idle;
  double iowait;
  double irq;
  double softirq;
  double ctxt;
  double intr;
  double blocked;
};

struct CpuInfo_t {
  char name[32];
  int user;
  int nice;
  int system;
  int idle;
  int iowait;
  int irq;
  int softirq;
  long ctxt;
  long intr;
  long blocked;
  uint64_t uptime_cs;
};

struct Memory_t {
    char name[32];
    long total;
    char name2[32];
    long free;
    char name3[32];
    long available;
};

enum ExcelWorkType {
  IDLE = 0,
  WORKING = 1,
};

class MonitorReport {
public:
  MonitorReport();
  ~MonitorReport();

  void init();

  void set_pid_stat(const st_pid& pid_stat,uint32_t get_curr,uint64_t now_time);
  void update(uint64_t now_time);
  void sync_work_type(void);
private:
  void save_excel(int prev, 
                  int curr,
                  uint64_t itv);

private:
  static std::vector<const char*> sheet_title;
  static std::vector<const char*> sheet_sys_title;
  bool report_switch = false;
  int32_t record_duration_min = 5;
  int32_t record_max_sheet_cnt = 10;
  int32_t record_interval_time_sec = 5;

  MonitorInfo monitor_info;
  uint64_t uptime_cs[2] = {0, 0};
  uint32_t curr = 1;
  ExcelTool excel_tool[2];

  ExcelWorkType work_type = ExcelWorkType::IDLE;
  ExcelWorkType get_work_type = ExcelWorkType::IDLE;
  //std::shared_ptr<xag_nav::os::StorageBase> storage_;
  CpuInfo_t cpu_info_last;
};

class ProcessMonitor {
public:
  ProcessMonitor();
  ~ProcessMonitor();

  void init();
  //void init(bool cgroup_switch,const rapidjson::Document& config_document);
  void loop(bool print_info);
  std::vector<ProgramState> get_program_state_vector(void);

private:
  st_pid *add_list_pid(pid_t pid, pid_t tgid);
  bool read_stats(int curr);
  void sfree_pids(bool force);
  bool read_proc_pid_stat(pid_t pid, 
                          st_pid *plist,
                          uint32_t *thread_nr, 
                          pid_t tgid, 
                          int curr);
  bool read_pid_stats(pid_t pid, 
                      st_pid *plist, 
                      uint32_t *thread_nr,
                      pid_t tgid, 
                      int curr);
  bool read_proc_pid_sched(pid_t pid, st_pid *plist, pid_t tgid, int curr);
  bool read_proc_pid_status(pid_t pid, st_pid *plist, pid_t tgid, int curr);
  bool read_proc_pid_io(pid_t pid, st_pid *plist, pid_t tgid, int curr);
  void read_task_stats(pid_t pid, st_pid *plist, int curr);
  int write_stats_core(int prev, int curr);
  int write_stats(int curr);
  int write_pid_task_all_stats(int prev, int curr,uint64_t itv);
  void set_pid_nonexistent(void);

private:
  std::unordered_map<pid_t,st_pid> all_process_map;
  std::vector<ProgramState> program_state_vector;
  uint64_t uptime_cs[2] = {0, 0};
  uint32_t curr = 1;
  MonitorReport monitor_report;
  // CgroupManager cgroup_manager_;
  // CpuAffinity cpu_affinity_;
  uint64_t io_uptime_cs[2] = {0, 0};
  uint64_t io_read_cnt_ = 0;
  uint32_t io_curr = 0;
};

}
}
}

#endif //PROCESS_MONITOR_H_
